// @HEADER
//*********************************************************************//
//  SiYuan: A numerical PDE solver                                     //
//  Copyright (2022) YUAN Xi                                           //
//  This Software is released under the BSD 2-Clause license detailed  //
//  in the file "LICENSE" in the top-level SiYuan directory            //
//*********************************************************************//
// @HEADER

#ifndef _CONVECTION_HPP
#define _CONVECTION_HPP

#include "Panzer_Dimension.hpp"
#include "Phalanx_Evaluator_Macros.hpp"
#include "Phalanx_MDField.hpp"

#include "Panzer_Evaluator_Macros.hpp"

using panzer::Cell;
using panzer::Point;
using panzer::Dim;

//**********************************************************************
//  Typical boundary conditions in Heat conduction analysis
//**********************************************************************

namespace SiYuan {

//! Scalar flux along surface 
template<typename EvalT, typename Traits>
class SFlux
  :
  public panzer::EvaluatorWithBaseImpl<Traits>,
  public PHX::EvaluatorDerived<EvalT, Traits>
{
  public:

    SFlux(const Teuchos::ParameterList& p);

    void postRegistrationSetup( typename Traits::SetupData d,
      PHX::FieldManager<Traits>& fm);

    void evaluateFields(typename Traits::EvalData d);

  private:

    using ScalarT = typename EvalT::ScalarT;

    XYZLib::variable<ScalarT> m_value;
    PHX::MDField<ScalarT> flux_;
};


//! Vector flux (= \nabla second order tensor \cdor normal) along surface 
template<typename EvalT, typename Traits>
class VectorFlux
  :
  public panzer::EvaluatorWithBaseImpl<Traits>,
  public PHX::EvaluatorDerived<EvalT, Traits>
{
  public:

    VectorFlux(const Teuchos::ParameterList& p);

    void postRegistrationSetup( typename Traits::SetupData d,
      PHX::FieldManager<Traits>& fm);

    void evaluateFields(typename Traits::EvalData d);

  private:

    using ScalarT = typename EvalT::ScalarT;

    XYZLib::variable<ScalarT> m_value;
    PHX::MDField<ScalarT> flux_;
  //  PHX::Device::size_type dim;
};


    
//! Convection: flux = coefficent * ( T - T_ambient )
template<typename EvalT, typename Traits>
class Convection
  :
  public panzer::EvaluatorWithBaseImpl<Traits>,
  public PHX::EvaluatorDerived<EvalT, Traits>
{
  public:

    Convection(const Teuchos::ParameterList& p);

    void postRegistrationSetup( typename Traits::SetupData d,
      PHX::FieldManager<Traits>& fm);

    void evaluateFields(typename Traits::EvalData d);

  private:

    using ScalarT = typename EvalT::ScalarT;

    double ambient_;
    double coefficient_;
    PHX::MDField<const ScalarT> temperature_;
    PHX::MDField<ScalarT> flux_;
  //  Kokkos::DynRankView<double,PHX::Device> TQp_;

  //  Kokkos::DynRankView<double,PHX::Device> basis;

    int num_cell, space_dim, num_cub_points, num_basis;
    std::string basis_name;
    std::size_t basis_index;
}; 


//! Radiate: flux = coefficent * ( T^4 - T_ambient^4 )
template<typename EvalT, typename Traits>
class Radiate
  :
  public panzer::EvaluatorWithBaseImpl<Traits>,
  public PHX::EvaluatorDerived<EvalT, Traits>
{
  public:

    Radiate(const Teuchos::ParameterList& p);

    void postRegistrationSetup( typename Traits::SetupData d,
      PHX::FieldManager<Traits>& fm);

    void evaluateFields(typename Traits::EvalData d);

  private:

    using ScalarT = typename EvalT::ScalarT;

    double ambient_;
    double coefficient_;
    PHX::MDField<const ScalarT> temperature_;
    PHX::MDField<ScalarT> flux_;

    int num_cell, space_dim, num_cub_points, num_basis;
    std::string basis_name;
    std::size_t basis_index;
}; 


}

#include "Convection_impl.hpp"

#endif
